package cn.iocoder.yudao.module.handguard.service.wechat;


import cn.iocoder.yudao.module.handguard.controller.app.wechat.AccessToken;
import cn.iocoder.yudao.module.handguard.dal.dataobject.referrerrecord.ReferrerRecordDO;
import cn.iocoder.yudao.module.handguard.dal.dataobject.user.UserDO;
import cn.iocoder.yudao.module.handguard.dal.mysql.referrerrecord.ReferrerRecordMapper;
import cn.iocoder.yudao.module.handguard.dal.mysql.user.MiniUserMapper;
import cn.iocoder.yudao.module.handguard.service.user.MiniUserService;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import com.alibaba.fastjson.JSON;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

@Service
@Validated
@Slf4j
public class WeChatServiceImpl implements WeChatService{



    @Value("${miniapp.env-version}")
    private String envVersion;

    @Resource
    private FileApi fileApi;

    @Resource
    private MiniUserMapper miniUserMapper;

    @Resource
    private ReferrerRecordMapper referrerRecordMapper;

    @Resource
    private MiniUserService miniUserService;

    //生成小程序二维码（获取小程序二维码，适用于需要的码数量较少的业务场景。通过该接口生成的小程序码，永久有效，有数量限制）
    @Override
    public String getWechatMiniScanUrl(Long userId, String miniPath) {
        // 获取调用凭证accessToken
        String accessToken = AccessToken.getAccessToken();
        String path = "";
        RestTemplate rest = new RestTemplate();
        InputStream inputStream = null;
        OutputStream outputStream = null;
        String imgUrl = "";
        try {
            String url = "https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token="+accessToken;
            log.info("url: "+url);
            Map<String,Object> param = new HashMap<>();
            param.put("path", path);
//            param.put("page", "pages/index/index"); // 路径 如果没有默认跳转到首页面微信小程序发布后才可以使用不能添加参数
            param.put("width", 430); //二维码尺寸
            param.put("is_hyaline", true); // 是否需要透明底色， is_hyaline 为true时，生成透明底色的小程序码 参数仅对小程序码生效
            param.put("auto_color", true); // 自动配置线条颜色，如果颜色依然是黑色，则说明不建议配置主色调 参数仅对小程序码生效
            Map<String,Object> line_color = new HashMap<>();
            line_color.put("r", 0);
            line_color.put("g", 0);
            line_color.put("b", 0);
            param.put("line_color", line_color);
            //log.info("调用生成微信URL接口传参:" + param);
            MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
            HttpEntity requestEntity = new HttpEntity(param, headers);
            ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class, new Object[0]);
            //log.info("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());
            byte[] result = entity.getBody();
            log.info(Base64.encodeBase64String(result));

            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            // 最后上传生成的文件名
            String finalFileName = System.currentTimeMillis() + "" + new SecureRandom().nextInt(0x0400) + ".jpg";

            imgUrl = fileApi.createFile("","",result);

            return imgUrl;
        } catch (Exception e) {
            log.error("调用小程序生成微信永久小程序码URL接口异常",e);
        } finally {
            if(inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return imgUrl;
    }

    //获取不限制的小程序码
    @Override
    public Map<String,Object> getWechatMiniRecommendScanUrl(Long userId, String miniPath) {
        Map<String,Object> map = new HashMap<>();
        //判断当前用户是否满足条件，身份证身份已经完善
        UserDO userDO = miniUserMapper.getUserInfo(userId);
        if (StringUtils.isEmpty(userDO.getQrCode())){
            // 获取调用凭证accessToken
            String accessToken = AccessToken.getAccessToken();
            //String accessToken = "82_fiWl5NMQL_-aXXMOYRlNoyaSLWdEG6wjAsBwFg-ccu-9RH9OJSApwVfNGeSg1iE2dl-nZ7WExUGjaIU6gsw92yvcAj8CrkGRyQXJVVep1xyEQApJ7HXOc98HVZEFTCiAFASGP";
            String path = "";
            RestTemplate rest = new RestTemplate();
            InputStream inputStream = null;
            OutputStream outputStream = null;
            String imgUrl = "";
            try {
                String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token="+accessToken;
                log.info("url: "+url);
                Map<String,Object> param = new HashMap<>();
                //param.put("path", path);
                param.put("page", path); // 路径 如果没有默认跳转到首页面,微信小程序发布后才可以使用，不能添加参数
                //param.put("page", "pages/index/binding");
                //param.put("check_path",false);//默认是true，检查page 是否存在，为 true 时 page 必须是已经发布的小程序存在的页面（否则报错）；为 false 时允许小程序未发布或者 page 不存在， 但page 有数量上限（60000个）请勿滥用。
                param.put("width", 285); //默认430，二维码的宽度，单位 px，最小 280px，最大 1280px
                param.put("is_hyaline", true); // 是否需要透明底色， is_hyaline 为true时，生成透明底色的小程序码 参数仅对小程序码生效
                param.put("auto_color", true); // 自动配置线条颜色，如果颜色依然是黑色，则说明不建议配置主色调 参数仅对小程序码生效
                Map<String,Object> line_color = new HashMap<>();
                line_color.put("r", 0);
                line_color.put("g", 0);
                line_color.put("b", 0);
                param.put("line_color", line_color);
                param.put("scene", String.valueOf(userId));//最大32字符
                param.put("env_version",envVersion);//要打开的小程序版本。正式版为 "release"，体验版为 "trial"，开发版为 "develop"。默认是正式版。
                //log.info("调用生成微信URL接口传参:" + param);
                MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
                HttpEntity requestEntity = new HttpEntity(param, headers);
                ResponseEntity<byte[]> entity = rest.exchange(url, HttpMethod.POST, requestEntity, byte[].class);
                //log.info("调用小程序生成微信永久小程序码URL接口返回结果:" + entity.getBody());
                byte[] result = entity.getBody();
                //log.info(Base64.encodeBase64String(result));

                //SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
                // 最后上传生成的文件名
                String finalFileName = System.currentTimeMillis() + "" + new SecureRandom().nextInt(0x0400) + ".jpg";
                //生成图片地址并且插入数据库
                imgUrl = fileApi.createWeChatScanFile(finalFileName,"",result);
                //log.info("图片url:" + imgUrl);
                //inputStream = new ByteArrayInputStream(result);
                map.put("code",200);
                map.put("message","二维码已生成");
                map.put("data",imgUrl);

                //更新用户表
                miniUserMapper.setUserQrCode(userId,imgUrl);

            } catch (Exception e) {
                log.error("调用小程序生成微信永久小程序码URL接口异常",e);
            } finally {
                if(inputStream != null){
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(outputStream != null){
                    try {
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }else if (StringUtils.isNotEmpty(userDO.getQrCode())){
            map.put("code",200);
            map.put("data",userDO.getQrCode());
            map.put("message","");
        }
//        else {
//            map.put("code",500);
//            map.put("data","");
//            map.put("message","身份证号未完善，无法生成推荐二维码！");
//        }
        return map;
    }

    @Override
    public Map<String, Object> getCheckBinding(Long userId,Long code) {
        Map<String, Object> map = new HashMap<>();
        if (userId.equals(code)){
            map.put("code",500);
            map.put("data","");
            map.put("message","无法绑定自己！");
            return map;
        }
        //校验当前人是否已经填写身份证号、并且是否已存在绑定了推荐人
        UserDO userDO = miniUserMapper.getUserInfo(userId);//客户
        //推荐人信息
        UserDO agentUser = miniUserMapper.getUserInfo(code);//推荐人
        if (userDO!=null){
            if (userDO.getReferrer()==null){
                //判断当前推荐人是否存在违规，自己绑定自己
                if (userDO.getIdentityCard()!=null){
                    if (agentUser.getIdentityCard().equals(userDO.getIdentityCard())){
                        map.put("code",500);
                        map.put("data",userDO.getQrCode());
                        map.put("message","推荐人证件号与和你一致，无法操作！");
                    }else {
                        map.put("code",200);
                        map.put("data","你的推荐人"+agentUser.getName());
                        map.put("message","校验通过");
                    }
                }else {
                    map.put("code",200);
                    map.put("data","你的推荐人"+agentUser.getName());
                    map.put("message","校验通过");
                }
            }else if(userDO.getReferrer()!=null){
                map.put("code",500);
                map.put("data",userDO.getQrCode());
                map.put("message","您已有推荐人！");
            }
            //else if(StringUtils.isEmpty(userDO.getIdentityCard())){
            //    map.put("code",500);
            //    map.put("data","");
            //    map.put("message","身份证号信息未完善，无法进行操作！");
            //}
        }else {
            map.put("code",500);
            map.put("data","");
            map.put("message","系统错误，请联系管理员！");
        }
        return map;
    }

    @Override
    @Transactional
    public Map<String, Object> affirm(Long userId, Long code) {
        Map<String, Object> map = new HashMap<>();
        //重复校验一遍
        map  = getCheckBinding(userId,code);
        if (map.get("code").equals(200)){
               miniUserMapper.affirmUser(userId,code);
                UserDO userDO = miniUserMapper.getUserInfo(userId);//客户
                //插入绑定记录
                ReferrerRecordDO recordDO = new ReferrerRecordDO();
                recordDO.setRecommendId(userId);//被推荐用户
                recordDO.setRecommendPhone(userDO.getMobile());
                recordDO.setUserId(code);//推荐人
                referrerRecordMapper.insert(recordDO);
                map.put("code",200);
                map.put("data","");
                map.put("message","绑定成功");
                return map;
        }else {
            map.put("code",500);
            map.put("data","操作失败");
            map.put("message","操作失败");
        }
        return map;
    }


}
